<template>
  <base-load-page :loadState="false" class="base-load-page">
    <template #head>
      <div style="padding-bottom: 15px" class="head-box">
        <div class="left-box">
          <base-input-search
            v-model="filterData.deptName"
            clearable
            placeholder="请输入部门名称"
            style="width: 100%"
            :prefixIcon="IconSearch"
            @submit="getAxiosData(true)"
          ></base-input-search>
        </div>
        <div class="right-box">
          <el-button type="success" :icon="IconSolarAddCircleLinear" @click="handleAdd()">新增</el-button>
        </div>
      </div>
    </template>
    <el-table
      ref="elTableRef"
      v-loading="baseData.loading"
      rowKey="deptId"
      border
      height="100%"
      :data="tableData"
      showOverflowTooltip
      stripe
      style="width: 100%"
      defaultExpandAll
    >
      <template #empty>
        <base-empty :description="description" :pageLoadButton="[{ text: '重新加载', callBack: () => getAxiosData() }]"></base-empty>
      </template>
      <el-table-column fixed label="部门名称" prop="deptName" minWidth="120"></el-table-column>
      <el-table-column label="创建时间" prop="createTime" minWidth="120"></el-table-column>
      <el-table-column fixed="right" label="状态" width="90" align="center" headerAlign="center">
        <template #default="{ row }">
          <el-switch
            v-model="row.status"
            style="--el-switch-on-color: var(--el-color-success); --el-switch-off-color: var(--el-color-danger)"
            inlinePrompt
            activeText="启用"
            inactiveText="停用"
            :activeValue="0"
            :inactiveValue="1"
            :loading="row._statusLoading"
            :beforeChange="() => handleSetStateSingle(row)"
          ></el-switch>
        </template>
      </el-table-column>
      <el-table-column fixed="right" label="操作" width="140" align="center" headerAlign="center">
        <template #default="{ row }">
          <el-button link type="primary" size="small" :icon="IconEdit" @click="openEdit(row)">编辑</el-button>
          <el-button link type="danger" size="small" :icon="IconDelete" @click="handleDel(row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    <add-edit-dept ref="addEditDeptRef" :deptList="tableData"></add-edit-dept>
  </base-load-page>
</template>

<script setup lang="ts">
  import IconSearch from '~icons/ep/search';
  import IconSolarAddCircleLinear from '~icons/solar/add-circle-linear';
  import IconDelete from '~icons/ep/delete';
  import IconEdit from '~icons/ep/edit';
  import addEditDept from './components/add-edit-dept.vue';
  import { type DeptItem, type DeptRequest, editSysDeptListAxios, getSysDeptListAxios, removeSysDeptAxios } from '@/api/permission-management';

  type _DeptItem = DeptItem & {
    /** 修改冻结状态的加载状态 */
    _statusLoading?: boolean;
  };

  interface DetpTreeNode<T> {
    deptId: string;
    parentId?: string;
    children?: DetpTreeNode<T>[];
    [key: string]: any;
  }
  const elTableRef: $RefComp<'ElTable'> = ref(null);
  const addEditDeptRef: $RefComp<typeof addEditDept> = ref(null);
  const baseData = shallowReactive({
    type: 'add' as 'add' | 'edit',
    /** 加载状态 */
    loading: true,
    /** 总数量 */
    total: 0,
  });

  const filterData: Ref<DeptRequest> = ref<DeptRequest>({
    deptId: '',
    parentId: '',
    deptName: '',
    status: '',
  });

  const tableData: Ref<DetpTreeNode<DeptItem>[]> = ref([]);
  const description = ref('');
  onMounted(() => {
    getAxiosData();
  });

  /**
   * 设置表格数据
   */
  async function getAxiosData(showLoading = true) {
    try {
      await nextTick();
      baseData.loading = Boolean(showLoading);
      const res = await getSysDeptListAxios(filterData.value);
      tableData.value = arrlistToTree(res.data, 'deptId');
      description.value = '暂无数据';
      baseData.loading = false;
    } catch (error) {
      baseData.loading = false;
      tableData.value = [];
      description.value = error.msg || '加载失败，-BD001';
    }
  }

  /** 跳转到新增视频页面 */
  function handleAdd() {
    addEditDeptRef.value?.show({
      type: 'add',
      addCallBack: () => {
        getAxiosData(false);
      },
    });
  }

  /** 编辑 */
  function openEdit(data: _DeptItem) {
    addEditDeptRef.value?.show({
      type: 'edit',
      data,
      editCallBack: () => {
        getAxiosData(false);
      },
    });
  }

  /** 删除 */
  function handleDel(row: _DeptItem) {
    ElMessageBox.confirm('删除后不可恢复，您确定删除吗？', '温馨提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning',
      draggable: true,
      beforeClose: async (action, instance, done) => {
        if (action === 'confirm') {
          instance.confirmButtonLoading = true;

          try {
            await removeSysDeptAxios(row.deptId);
            await getAxiosData(false);
            instance.confirmButtonLoading = false;
            done();
            ElToast.success('删除成功');
          } catch (error) {
            instance.confirmButtonLoading = false;
            ElToast.error(error.msg || '删除失败，-BD004');
          }
        } else {
          done();
        }
      },
    });
  }

  /** 修改单个状态 */
  async function handleSetStateSingle(row: _DeptItem): Promise<boolean> {
    const name = row.status === 0 ? '停用' : '启用';
    try {
      row._statusLoading = true;
      await editSysDeptListAxios({
        parentId: row.parentId,
        deptId: row.deptId,
        deptName: row.deptName,
        orderNum: row.orderNum,
        status: row.status === 0 ? 1 : 0,
      });
      row._statusLoading = false;
      ElToast.success(`${name}成功`);
      return Promise.resolve(true);
    } catch (error) {
      row._statusLoading = false;

      ElToast.error(error.msg || `${name}失败，-BD004`);
      return Promise.reject(false);
    }
  }

  /** 部门列表转部门树 */
  function arrlistToTree(arr: DeptItem[], flay: keyof DeptItem) {
    const map = new Map<string, DetpTreeNode<DeptItem>>();
    const tree: DetpTreeNode<DeptItem>[] = [];
    arr.forEach((item) => {
      const node: DetpTreeNode<DeptItem> = {
        ...item,
        children: [],
      };
      map.set(node.deptId, node);
    });
    arr.forEach((item) => {
      const node = map.get(item[flay] as string);
      if (item.parentId) {
        const parentNode = map.get(item.parentId);
        if (parentNode) {
          parentNode.children!.push(node!);
        } else {
          tree.push(node!);
        }
      } else {
        tree.push(node!);
      }
    });

    return tree;
  }
</script>

<style lang="scss" scoped>
  .pagination-box {
    @include flex(row, nowrap, center, center, center);
    padding-top: 15px;
  }

  .head-box {
    @include flex(row, nowrap, flex-start, center, center);

    .left-box {
      display: grid;
      flex: 1;
      grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
      grid-gap: 15px;
      margin-right: 15px;
    }
  }
</style>
